package week4;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See
 * the NOTICE file distributed with this work for additional information regarding copyright ownership. The
 * ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file
 * except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 *
 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing,
 * software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing
 * permissions and 015 * limitations under the License. 016
 */
import java.io.BufferedReader;

import org.w3c.dom.*;

import javax.xml.parsers.*;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Date;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.CharArraySet;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.jsoup.Jsoup;
import org.jsoup.parser.Parser;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * Index all text files under a directory. 048 *
 * <p>
 * 049 * This is a command-line application demonstrating simple Lucene indexing. 050 * Run it with no command-line
 * arguments for usage information. 051
 */
public class IndexFilesChinese {//useful

    private IndexFilesChinese() {
    }

    /** Index all text files under a directory. */
    public static void main(String[] args) {
        String usage = "java org.apache.lucene.demo.IndexFiles"
                + " [-index INDEX_PATH] [-docs DOCS_PATH] [-update]\n\n"
                + "This indexes the documents in DOCS_PATH, creating a Lucene index"
                + "in INDEX_PATH that can be searched with SearchFiles";
        String indexPath = "index_chinese";//索引的目录
        String docsPath = "tzc_xml";//小说源文件目录
        boolean create = true;
        if (docsPath == null) { System.err.println("Usage: " + usage);System.exit(1); }
        final Path docDir = Paths.get(docsPath);
        if (!Files.isReadable(docDir)) {
            System.out.println("Document directory '" + docDir.toAbsolutePath() +
                    "' does not exist or is not readable, please check the path");
            System.exit(1);
        }
        Date start = new Date();
        try {
            System.out.println("Indexing to directory '" + indexPath + "'...");

            Directory dir = FSDirectory.open(Paths.get(indexPath));
            Analyzer analyzer =new IKAnalyzer(true,true,false);
            IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
            if (create) { iwc.setOpenMode(OpenMode.CREATE);//重建索引
                 } else { iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);//更新索引
            }
            IndexWriter writer = new IndexWriter(dir, iwc);
            indexDocs(writer, docDir);//建索引
            writer.close();
            Date end = new Date();
            System.out.println(end.getTime() - start.getTime() + " total milliseconds");
        } catch (IOException e) {
            System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); }
    }


    static void indexDocs(final IndexWriter writer, Path path) throws IOException {
        if (Files.isDirectory(path)) {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    try {
                        indexDoc(writer, file, attrs.lastModifiedTime().toMillis());
                        //indexDocScenes(writer, file, attrs.lastModifiedTime().toMillis());
                    } catch (IOException ignore) {
                        // don't index files that can't be read.
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        } else {
            indexDoc(writer, path, Files.getLastModifiedTime(path).toMillis());
            //indexDocScenes(writer, path, Files.getLastModifiedTime(path).toMillis());

        }
    }

    /** Indexes a single document */
    static void indexDocOriginal(IndexWriter writer, Path file, long lastModified) throws IOException {
        try (InputStream stream = Files.newInputStream(file)) {
            // make a new, empty document
            Document doc = new Document();

            // Add the path of the file as a field named "path". Use a
            // field that is indexed (i.e. searchable), but don't tokenize
            // the field into separate words and don't index term frequency
            // or positional information:
            Field pathField = new StringField("path", file.toString(), Field.Store.YES);
            doc.add(pathField);

            // Add the last modified date of the file a field named "modified".
            // Use a LongPoint that is indexed (i.e. efficiently filterable with
            // PointRangeQuery). This indexes to milli-second resolution, which
            // is often too fine. You could instead create a number based on
            // year/month/day/hour/minutes/seconds, down the resolution you require.
            // For example the long value 2011021714 would mean
            // February 17, 2011, 2-3 PM.
            doc.add(new LongPoint("modified", lastModified));

            // Add the contents of the file to a field named "contents". Specify a Reader,
            // so that the text of the file is tokenized and indexed, but not stored.
            // Note that FileReader expects the file to be in UTF-8 encoding.
            // If that's not the case searching for special characters will fail.
            doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));


            // Indexing personae in plays

            String persona = "";

            String xml = readFile(file.toString(), StandardCharsets.UTF_8);
            String extension = "";
            int i = file.toString().lastIndexOf('.');
            if (i > 0) {
                extension = file.toString().substring(i+1);
            }
            if(extension.equals("xml")){



                org.jsoup.nodes.Document newdoc = Jsoup.parse(xml,file.toString(),Parser.xmlParser());


                for (org.jsoup.nodes.Element e : newdoc.select("persona")) {
                    persona += " ; " + e.text();

                }

            }

            doc.add(new TextField("persona", persona, Field.Store.NO));


            // Indexing stagedir


            String stagedirs = "";

            String xml1 = readFile(file.toString(), StandardCharsets.UTF_8);
            String extension1 = "";
            int j = file.toString().lastIndexOf('.');
            if (j > 0) {
                extension1 = file.toString().substring(j+1);
            }
            if(extension1.equals("xml")){



                org.jsoup.nodes.Document newdoc = Jsoup.parse(xml1,file.toString(),Parser.xmlParser());


                for (org.jsoup.nodes.Element e : newdoc.select("stagedir")) {
                    stagedirs += " ; " + e.text();

                }

            }

            doc.add(new TextField("stagedir", stagedirs, Field.Store.NO));


            if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
                // New index, so we just add the document (no old document can be there):
//                System.out.println("adding " + file);
                writer.addDocument(doc);
            } else {
                // Existing index (an old copy of this document may have been indexed) so
                // we use updateDocument instead to replace the old one matching the exact
                // path, if present:
                System.out.println("updating " + file);
                writer.updateDocument(new Term("path", file.toString()), doc);
            }
        }
    }


    static void indexDoc(IndexWriter writer, Path file, long lastModified) throws IOException {
        try (InputStream stream = Files.newInputStream(file)) {
            String xml = readFile(file.toString(), StandardCharsets.UTF_8);
            String extension = "";
            int i = file.toString().lastIndexOf('.');
            if (i > 0) { extension = file.toString().substring(i+1); }
            if(extension.equals("xml")){
                org.jsoup.nodes.Document newdoc = Jsoup.parse(xml,file.toString(),Parser.xmlParser()); //Jsoup解析xml文档
                String playTitle = newdoc.select("title").get(0).text();//获取标题
                for(org.jsoup.nodes.Element act : newdoc.select("act")) {//对正文建索引
                    String actTitle = act.select("title").get(0).text();
                    for (org.jsoup.nodes.Element sceneElement : act.select("scene")) {
                        String scene = sceneElement.select("title").get(0).text();
                        //String stagedir = sceneElement.select("stagedir").get(0).text();
                        for (org.jsoup.nodes.Element speech : sceneElement.select("speech")) {
                            Document doc = new Document();
                            Field pathField = new StringField("path", file.toString(), Field.Store.YES);
                            doc.add(pathField);
                            doc.add(new LongPoint("modified", lastModified));
                            doc.add(new TextField("contents", speech.text(), Field.Store.NO));//建立正文索引
                            doc.add(new TextField("title", playTitle,Field.Store.YES));//建立标题索引
                            doc.add(new StringField("act", actTitle,Field.Store.YES));
                            doc.add(new TextField("scene", scene,Field.Store.YES));
                            if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
//                                System.out.println("adding " + file);
                                writer.addDocument(doc);
                            } else { System.out.println("updating " + file);
                                writer.updateDocument(new Term("path", file.toString()), doc); }
                        }} } } } }

    static String readFile(String path, Charset encoding)
            throws IOException
    {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return new String(encoded, encoding);
    }
}
